﻿using System.ComponentModel;
using System.Xml.Linq;
using System.Linq;
using System.Collections.Generic;

using DbSharp.Framework.CaseFile.Parser;
using DbSharp.Framework.DbObject;
using DbSharp.Framework.CaseFile;
using System;
using System.Collections.ObjectModel;
using DbSharp.Framework.Common;


namespace DbSharp.Framework.CaseFile
{

    /// <summary>
    /// Performance test case entity
    /// </summary>
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class PerformanceTestCase
    {
        #region Private members

        private List<SetupAction> m_ListSetupAction = new List<SetupAction>();
        private List<SetupAction> m_ListTeardownAction = new List<SetupAction>();
        private IStatementDeclaration m_StatementObj;
        private XElement m_procInputArgsElement;
        private string m_CaseName;
        private IResultsetOutputSetting m_OutputSetting;
        private List<string> m_Tags = new List<string>();
        private string m_TagsValue;
 
        #endregion


        public PerformanceTestCase(string caseName, IEnumerable<IStatementDeclaration> listStatement, string statementAlias, XElement procInputArgsElement, XElement globalSettingElement)
        {
            m_CaseName = caseName;
            DefaultRsOutputSettingParser defaultOutputSettingParser = new DefaultRsOutputSettingParser(globalSettingElement);
            m_OutputSetting = defaultOutputSettingParser.Setting;
            m_procInputArgsElement = procInputArgsElement;

            IStatementDeclaration statementDeclaration = listStatement.FirstOrDefault(
                stmt => StatementDeclarationExt.FindByAlias(stmt, statementAlias));

            if (statementDeclaration == null)
            {
                string messageFmt = "statementAlias'{0}' used in Perf Case '{1}' cannot be found in sqlDeclarations and procDeclarations";
                string message = string.Format(messageFmt, statementAlias, m_CaseName);
                throw new DbSharpException(message);
            }

            //override the inputArguments of the procDeclaration
            var inputArgsExtractor =new StatementInputArgsProcessor(m_procInputArgsElement, statementDeclaration);
            m_StatementObj = inputArgsExtractor.StatementWithInArgValues;

        }


        #region Public Methods/Properties

        /// <summary>
        /// For export performaceTest, one ResultsetSection object need to be created, 
        /// </summary>
        /// <returns></returns>
        public ResultsetSection ResultsetSection
        {
            get
            {
                ResultsetSection section = new ResultsetSection();
                section.StatementDeclaration = m_StatementObj;
                section.IsTargetResultset = true;
                section.OutputSetting = m_OutputSetting;
                return section;
            }
        }

        public IStatementDeclaration StatementDeclaration
        {
            get { return m_StatementObj; }
        }

        public string TestCaseName { get; set; }
        public string TestCaseRemark { get; set; }
        public bool IgnoreThis{ get; set; }
        public bool TestInSandbox { get; set; }
        public string TagsValue
        {
            get
            {
                return m_TagsValue;
            }
            set
            {
                m_TagsValue = value;
                m_Tags.Clear();
                var tags = m_TagsValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var tag in tags)
                {
                    m_Tags.Add(tag.Trim());
                }
            }
        }
        public List<string> Tags
        {
            get { return m_Tags; }
        }


        public IResultsetOutputSetting OutputSetting
        {
            get { return m_OutputSetting; }
        }

        public override string ToString()
        {
            return this.TestCaseName;
        }

        public void AddSetupStatement(SetupAction action)
        {
            m_ListSetupAction.Add(action);
        }

        public void AddTeardownStatment(SetupAction action)
        {
            m_ListTeardownAction.Add(action);
        }


        public ReadOnlyCollection<SetupAction> ListSetupAction
        {
            get { return new ReadOnlyCollection<SetupAction>(m_ListSetupAction); }
        }

        public ReadOnlyCollection<SetupAction> ListTeardownAction
        {
            get { return new ReadOnlyCollection<SetupAction>(m_ListTeardownAction); }
        }
        #endregion

    }
}
